package com.millstein.tsinglog.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.millstein.tsinglog.commons.constant.SystemConstant;
import com.millstein.tsinglog.commons.enums.ResultCode;
import com.millstein.tsinglog.exception.TsinglogException;
import com.millstein.tsinglog.commons.service.BaseService;
import com.millstein.tsinglog.utils.EncryptUtils;
import com.millstein.tsinglog.utils.PhoneFormatCheckUtils;
import com.millstein.tsinglog.mapper.biz.RoleMapper;
import com.millstein.tsinglog.mapper.biz.UserMapper;
import com.millstein.tsinglog.model.dto.user.ChangePasswordDTO;
import com.millstein.tsinglog.model.dto.user.UserAssignRoleDTO;
import com.millstein.tsinglog.model.dto.user.UserLoginDTO;
import com.millstein.tsinglog.model.dto.user.UserSaveDTO;
import com.millstein.tsinglog.model.pojo.Role;
import com.millstein.tsinglog.model.pojo.User;
import com.millstein.tsinglog.model.vo.result.PageResult;
import com.millstein.tsinglog.model.vo.sys.UserVo;
import com.millstein.tsinglog.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserServiceImpl extends BaseService implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Override
    public PageResult<UserVo> getUserByPage(Integer currentPage, Integer pageSize, String keyword) {

        if (currentPage == null) {
            currentPage = SystemConstant.DEFAULT_CURRENT_PAGE;
        }
        if (pageSize == null) {
            pageSize = SystemConstant.DEFAULT_PAGE_SIZE;
        }

        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();

        if (StringUtils.isNotBlank(keyword)) {
            criteria.orLike("username", "%" + keyword + "%");
            criteria.orLike("nickname", "%" + keyword + "%");
            criteria.orLike("mobile", "%" + keyword + "%");
        }

        criteria.andEqualTo("status", SystemConstant.STATUS_ENTITY_NORMAL);

        example.setOrderByClause("role_id asc, update_time desc");

        PageHelper.startPage(currentPage, pageSize);
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(users)) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }

        List<UserVo> vos = new ArrayList<>();
        for (User user : users) {
            UserVo vo = new UserVo(user);

            // 查询roleName并赋值给vo
            Role role = new Role();
            role.setId(user.getRoleId());
            Role dbRole = roleMapper.selectOne(role);

            vo.setRoleName(dbRole.getRoleName());
            vos.add(vo);
        }

        PageInfo pageInfo = new PageInfo(users);

        return new PageResult(pageInfo.getTotal(), pageInfo.getPages(), vos);
    }

    @Override
    public void resetPassword(UserLoginDTO userLoginDTO) {

        User dbUser = this.getUserByUsername(userLoginDTO.getUsername());
        if (dbUser == null) {
            throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
        }

        String rawPassword = userLoginDTO.getPassword();
        String password = new SimpleHash(SystemConstant.ENCRYPT_ARITHMETIC, rawPassword, dbUser.getSalt(),
                SystemConstant.ENCRYPT_TIMES).toString();
        dbUser.setPassword(password);
        dbUser.setUpdateTime(getCurrentDateStr());

        int result = userMapper.updateByPrimaryKeySelective(dbUser);
        if (result != 1) {
            throw new TsinglogException(ResultCode.UPDATE_FAILURE);
        }

    }

    @Override
    public void assignRole(UserAssignRoleDTO userAssignRoleDTO) {

        User dbUser = this.getUserByUsername(userAssignRoleDTO.getUsername());
        if (dbUser == null) {
            throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
        }

        dbUser.setRoleId(userAssignRoleDTO.getRoleId());
        dbUser.setUpdateTime(getCurrentDateStr());

        int result = userMapper.updateByPrimaryKeySelective(dbUser);
        if (result != 1) {
            throw new TsinglogException(ResultCode.UPDATE_FAILURE);
        }
    }

    @Override
    public void insertUser(UserSaveDTO userSaveDTO) {

        // 1.对内容进行校验
        if (!PhoneFormatCheckUtils.isPhoneLegal(userSaveDTO.getMobile())) {
            throw new TsinglogException(ResultCode.IS_NOT_PHONE_NUMBER);
        }

        // 生成加密盐
        String salt = EncryptUtils.SaltBuild();

        String password = new SimpleHash(SystemConstant.ENCRYPT_ARITHMETIC,
                SystemConstant.DEFAULT_PASSWORD, salt, SystemConstant.ENCRYPT_TIMES).toString();

        User user = this.getUserByUsername(userSaveDTO.getUsername());

        if (user != null) {
            throw new TsinglogException(ResultCode.EXIST_USER_NAME);
        }

        user = new User();
        user.setUsername(userSaveDTO.getUsername());
        user.setPassword(password);
        user.setSalt(salt);
        // TODO 暂时添加的用户只用这一张图片作为头像
        user.setAvatar(SystemConstant.DEFAULT_USER_AVATAR);
        user.setNickname(userSaveDTO.getNickname());
        user.setMobile(userSaveDTO.getMobile());
        user.setRoleId(userSaveDTO.getRoleId());
        user.setUsable(SystemConstant.USABLE_ENTITY_ON);
        user.setLoginCount(SystemConstant.DEFAULT_LOGIN_COUNT);
        user.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        user.setCreateTime(getCurrentDateStr());
        user.setUpdateTime(getCurrentDateStr());

        int result = userMapper.insert(user);
        if (result != 1) {
            throw new TsinglogException(ResultCode.INSERT_FAILURE);
        }

    }

    @Override
    public void updateUser(UserSaveDTO userSaveDTO) {

        // 1.手机号码校验
        if (!PhoneFormatCheckUtils.isPhoneLegal(userSaveDTO.getMobile())) {
            throw new TsinglogException(ResultCode.IS_NOT_PHONE_NUMBER);
        }
        // 2.重名校验
        User _user = this.getUserByUsername(userSaveDTO.getUsername());
        if (_user != null) {
            throw new TsinglogException(ResultCode.EXIST_USER_NAME);
        }
        // 3.参数完整性校验
        if (userSaveDTO.getId() == null) {
            throw new TsinglogException(ResultCode.PARAM_NOT_COMPLETE);
        }
        // 4.是否有记录校验
        User dbUser = userMapper.selectUserByPrimaryKey(userSaveDTO.getId());
        if (dbUser == null) {
            throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
        }

        dbUser.setUsername(userSaveDTO.getUsername());
        dbUser.setNickname(userSaveDTO.getNickname());
        dbUser.setMobile(userSaveDTO.getMobile());
        dbUser.setRoleId(userSaveDTO.getRoleId());
        dbUser.setUpdateTime(getCurrentDateStr());

        int result = userMapper.updateByPrimaryKey(dbUser);
        if (result != 1) {
            throw new TsinglogException(ResultCode.UPDATE_FAILURE);
        }

    }

    @Override
    public void changeUsable(Long id, Short usable) {
        if (id == null || usable == null) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }
        User dbUser = userMapper.selectUserByPrimaryKey(id);
        if (dbUser == null) {
            throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
        }

        dbUser.setUsable(usable);
        dbUser.setUpdateTime(getCurrentDateStr());

        int result = userMapper.updateByPrimaryKeySelective(dbUser);
        if (result != 1) {
            throw new TsinglogException(ResultCode.UPDATE_FAILURE);
        }

    }

    @Override
    @Transactional
    public void deleteByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }

        for (Long id : ids) {
            User dbUser = userMapper.selectUserByPrimaryKey(id);
            if (dbUser == null) {
                throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
            }
            dbUser.setStatus(SystemConstant.STATUS_ENTITY_DELETE);
            dbUser.setUpdateTime(getCurrentDateStr());

            int result = userMapper.updateByPrimaryKeySelective(dbUser);
            if (result != 1) {
                throw new TsinglogException(ResultCode.UPDATE_FAILURE);
            }
        }
    }

    @Override
    public Integer getUserCountByRole(Long roleId) {

        if (roleId == null) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }

        User user = new User();
        user.setRoleId(roleId);
        user.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);

        List<User> list = userMapper.select(user);
        if (CollectionUtils.isEmpty(list)) {
            return 0;
        } else {
            return list.size();
        }
    }

    /**
     * 根据用户名查询用户信息
     * 调用这个方法时需要自己对结果进行判断
     * @param username
     * @return
     */
    @Override
    public User getUserByUsername(String username) {
        User criteria = new User();
        criteria.setUsername(username);
        criteria.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        return userMapper.select(criteria).size() == 0 ? null: userMapper.select(criteria).get(0);

    }

    @Override
    public void changePassword(ChangePasswordDTO changePasswordDTO) {

        String username = changePasswordDTO.getUsername();
        String oldPassword = changePasswordDTO.getOldPassword();

        // 将原密码加密
        User dbUser = this.getUserByUsername(username);
        if (dbUser == null) {
            throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
        }

        String encryptPassword = new SimpleHash(SystemConstant.ENCRYPT_ARITHMETIC, oldPassword,
                dbUser.getSalt(), SystemConstant.ENCRYPT_TIMES).toString();
        if (!encryptPassword.equals(dbUser.getPassword())) {
            throw new TsinglogException(ResultCode.INCORRECT_OLD_PASSWORD);
        }

        String newPassword = new SimpleHash(SystemConstant.ENCRYPT_ARITHMETIC,
                changePasswordDTO.getNewPassword(), dbUser.getSalt(), SystemConstant.ENCRYPT_TIMES).toString();

        dbUser.setPassword(newPassword);
        dbUser.setUpdateTime(getCurrentDateStr());

        int result = userMapper.updateByPrimaryKey(dbUser);
        if (result != 1) {
            throw new TsinglogException(ResultCode.UPDATE_FAILURE);
        }
    }

    @Override
    public List<String> getUserByCode(String code) {
        if (StringUtils.isBlank(code)) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }
        return userMapper.selectUserByCode(code);
    }
}
